using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.IO;

using PUPFILELib;
using Interop.MSCSAspHelp;
using Microsoft.CommerceServer.Runtime;

namespace ReadSiteServerConfigFiles
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		/// <summary>
		/// Structured File access.
		/// </summary>
		private System.Windows.Forms.TreeView treeView1;
		private System.Windows.Forms.OpenFileDialog openSiteServerCfgFileDialog;

		private string fileName = string.Empty;
		private string fileDest= string.Empty;

		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem menuItem4;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.MenuItem menuItem6;
		private System.Windows.Forms.Splitter splitter1;
		private System.Windows.Forms.ListView listView1;
		private System.Windows.Forms.ColumnHeader cKey;
		private System.Windows.Forms.ColumnHeader cValue;
		private System.Windows.Forms.MenuItem menuItem7;
		private System.Windows.Forms.MenuItem menuItem8;

		IFileDocument fileDoc = new FileDocumentClass();
		Microsoft.CommerceServer.Runtime.IDictionary dict = new DictionaryClass();
		private System.Windows.Forms.SaveFileDialog saveFileDialog1;
		private System.Windows.Forms.ContextMenu contextMenu1;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.MenuItem menuItem10;
		private System.Windows.Forms.MenuItem menuItem11;

		private const int STGM_SIMPLE = 0x08000000;
		private const int STGM_READ = 0x00000000;
		private const int STGM_SHARE_DENY_NONE = 0x00000020;
		private const int  STGM_SHARE_EXCLUSIVE = 0x00000010;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;


		/// <summary>
		/// Structured File access.
		/// </summary>
		class ole32
		{
			[DllImport("ole32.dll")]
			public static extern int StgOpenStorage (
				[MarshalAs(UnmanagedType.LPWStr)] string wcsName,
				IntPtr stgPriority,
				int grfMode,
				IntPtr snbExclude,
				int reserved,
				out UCOMIStorage storage
				);
			
			[DllImport("ole32.dll")]
			public static extern int StgIsStorageFile(
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsName
				);
		}

		/// <summary>
		/// 
		/// </summary>
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000000d-0000-0000-C000-000000000046")]
			interface IEnumSTATSTG 
		{
			[PreserveSig]
			int Next(uint celt, out STATSTG rgelt, out uint pceltFetched);
			[PreserveSig]
			int Skip(uint celt);
			[PreserveSig]
			int Reset();
			[PreserveSig]
			int Clone(out IEnumSTATSTG ppenum);
		}

		/// <summary>
		/// Interface to Structured File.
		/// </summary>
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000000b-0000-0000-C000-000000000046")]
			interface UCOMIStorage
		{
			[PreserveSig]
			int CreateStream(
				[MarshalAs(UnmanagedType.LPWStr)] string wcsName,
				int grfMode, //Access mode for the new stream
				int reserved1, //Reserved; must be zero
				int reserved2, //Reserved; must be zero
				out UCOMIStream stream //Pointer to output variable
				);

			[PreserveSig]
			int OpenStream(
				[MarshalAs(UnmanagedType.LPWStr)] string wcsName,
				IntPtr reserved1, //Reserved; must be NULL
				int grfMode, //Access mode for the new stream
				int reserved2, //Reserved; must be zero
				out UCOMIStream stream //Pointer to output variable
				);

			[PreserveSig]
			int CreateStorage(
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
				int grfMode,
				int reserved1,
				int reserved2,
				out UCOMIStorage ppstg);

			[PreserveSig]
			int OpenStorage(
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
				UCOMIStorage pstgPriority,
				int grfMode,
				[MarshalAs(UnmanagedType.LPWStr)] string snbExclude,
				int reserved,
				out UCOMIStorage ppstg
				);

			[PreserveSig]
			int CopyTo(
				int ciidExclude,
				Guid rgiidExclude,
				[MarshalAs(UnmanagedType.LPWStr)] string snbExclude,
				UCOMIStorage pstgDest
				);
        
			[PreserveSig]
			int MoveElementTo(
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
				UCOMIStorage pstgDest,
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName,
				int grfFlags
				);

			[PreserveSig]
			int Commit(
				int grfCommitFlags
				);

			[PreserveSig]
			int Revert();

			[PreserveSig]
			int EnumElements( 
				int reserved1,		//Reserved; must be zero
				IntPtr reserved2,	//Reserved; must be NULL
				int reserved3,		//Reserved; must be zero
				out IEnumSTATSTG ppenum
				);
        
			[PreserveSig]
			int DestroyElement(
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsName
				);
        
			[PreserveSig]
			int RenameElement(
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsOldName,
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName
				);
        
			[PreserveSig]
			int SetElementTimes(
				[MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
				DateTime pctime,
				DateTime patime,
				DateTime pmtime
				);
        
			[PreserveSig]
			int SetClass(
				Guid clsid
				);
        
			[PreserveSig]
			int SetStateBits(
				int grfStateBits,
				int grfMask
				);
        
			[PreserveSig]
			int Stat(
				out STATSTG pstatstg,
				int grfStatFlag
				);
		}

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.treeView1 = new System.Windows.Forms.TreeView();
			this.openSiteServerCfgFileDialog = new System.Windows.Forms.OpenFileDialog();
			this.mainMenu1 = new System.Windows.Forms.MainMenu();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.menuItem7 = new System.Windows.Forms.MenuItem();
			this.menuItem8 = new System.Windows.Forms.MenuItem();
			this.menuItem4 = new System.Windows.Forms.MenuItem();
			this.menuItem5 = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.menuItem6 = new System.Windows.Forms.MenuItem();
			this.splitter1 = new System.Windows.Forms.Splitter();
			this.listView1 = new System.Windows.Forms.ListView();
			this.cKey = new System.Windows.Forms.ColumnHeader();
			this.cValue = new System.Windows.Forms.ColumnHeader();
			this.contextMenu1 = new System.Windows.Forms.ContextMenu();
			this.menuItem9 = new System.Windows.Forms.MenuItem();
			this.menuItem10 = new System.Windows.Forms.MenuItem();
			this.menuItem11 = new System.Windows.Forms.MenuItem();
			this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
			this.SuspendLayout();
			// 
			// treeView1
			// 
			this.treeView1.Dock = System.Windows.Forms.DockStyle.Left;
			this.treeView1.ImageIndex = -1;
			this.treeView1.Location = new System.Drawing.Point(0, 0);
			this.treeView1.Name = "treeView1";
			this.treeView1.SelectedImageIndex = -1;
			this.treeView1.Size = new System.Drawing.Size(144, 273);
			this.treeView1.TabIndex = 3;
			this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
			// 
			// mainMenu1
			// 
			this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem1,
																					  this.menuItem2});
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 0;
			this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem3,
																					  this.menuItem7,
																					  this.menuItem8,
																					  this.menuItem4,
																					  this.menuItem5});
			this.menuItem1.Text = "&File";
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 0;
			this.menuItem3.Text = "&Open";
			this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);
			// 
			// menuItem7
			// 
			this.menuItem7.Index = 1;
			this.menuItem7.Text = "&Save";
			this.menuItem7.Click += new System.EventHandler(this.menuItem7_Click);
			// 
			// menuItem8
			// 
			this.menuItem8.Index = 2;
			this.menuItem8.Text = "Save &As...";
			this.menuItem8.Click += new System.EventHandler(this.menuItem8_Click);
			// 
			// menuItem4
			// 
			this.menuItem4.Index = 3;
			this.menuItem4.Text = "-";
			// 
			// menuItem5
			// 
			this.menuItem5.Index = 4;
			this.menuItem5.Text = "&Close";
			this.menuItem5.Click += new System.EventHandler(this.menuItem5_Click);
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 1;
			this.menuItem2.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem6});
			this.menuItem2.Text = "&Help";
			// 
			// menuItem6
			// 
			this.menuItem6.Index = 0;
			this.menuItem6.Text = "&About";
			this.menuItem6.Click += new System.EventHandler(this.menuItem6_Click);
			// 
			// splitter1
			// 
			this.splitter1.Location = new System.Drawing.Point(144, 0);
			this.splitter1.Name = "splitter1";
			this.splitter1.Size = new System.Drawing.Size(3, 273);
			this.splitter1.TabIndex = 4;
			this.splitter1.TabStop = false;
			// 
			// listView1
			// 
			this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
																						this.cKey,
																						this.cValue});
			this.listView1.ContextMenu = this.contextMenu1;
			this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.listView1.Location = new System.Drawing.Point(147, 0);
			this.listView1.Name = "listView1";
			this.listView1.Size = new System.Drawing.Size(245, 273);
			this.listView1.TabIndex = 5;
			this.listView1.View = System.Windows.Forms.View.Details;
			// 
			// cKey
			// 
			this.cKey.Text = "Key";
			this.cKey.Width = 112;
			// 
			// cValue
			// 
			this.cValue.Text = "Value";
			this.cValue.Width = 128;
			// 
			// contextMenu1
			// 
			this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						 this.menuItem9,
																						 this.menuItem10,
																						 this.menuItem11});
			// 
			// menuItem9
			// 
			this.menuItem9.Index = 0;
			this.menuItem9.Text = "Edit";
			this.menuItem9.Click += new System.EventHandler(this.menuItem9_Click);
			// 
			// menuItem10
			// 
			this.menuItem10.Index = 1;
			this.menuItem10.Text = "Save";
			this.menuItem10.Click += new System.EventHandler(this.menuItem7_Click);
			// 
			// menuItem11
			// 
			this.menuItem11.Index = 2;
			this.menuItem11.Text = "Save as..";
			this.menuItem11.Click += new System.EventHandler(this.menuItem8_Click);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(392, 273);
			this.Controls.Add(this.listView1);
			this.Controls.Add(this.splitter1);
			this.Controls.Add(this.treeView1);
			this.Menu = this.mainMenu1;
			this.Name = "Form1";
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.Text = "Read Site Server Config Files";
			this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void loadConfigSettings(string file, CompoundFile objCompndFile)
		{
			Int64 hr = 0;

			// clean up our work space
			listView1.Items.Clear();
			treeView1.Nodes.Clear();

			// set prop
			TreeNode tn = treeView1.Nodes.Add(file);
			
			// is the file a compound file?
			hr = ole32.StgIsStorageFile(file);

			if(0==hr)
			{
				UCOMIStorage storage = null;
				int grfMode = STGM_READ | STGM_SHARE_DENY_NONE;
				int hResult = ole32.StgOpenStorage(fileName, IntPtr.Zero, grfMode, IntPtr.Zero, 0, out storage);
				if(hResult==0)
				{
					DisplayStorageTree(fileName, storage, tn);
				}
				else
				{
					MessageBox.Show("Error reading file lookup error code: "+hResult);
				}
			}
			else
			{
				MessageBox.Show("Not a valid csc file!");
			}
		}

		private void menuItem3_Click(object sender, System.EventArgs e)
		{
			CompoundFile g_objCompoundFile = new CompoundFileClass();
			openSiteServerCfgFileDialog.InitialDirectory = @"C:\";
			openSiteServerCfgFileDialog.Filter = "Site Server Config files (*.csc)|*.csc|All files (*.*)|*.*";
			
			if(openSiteServerCfgFileDialog.ShowDialog() == DialogResult.OK)
			{
				fileName = openSiteServerCfgFileDialog.FileName;
				if(fileName!= null)
				{
					loadConfigSettings(fileName, g_objCompoundFile);
				}
			}
		}

		private void menuItem6_Click(object sender, System.EventArgs e)
		{
			About frmAbout = new About();
			frmAbout.ShowDialog();
		}

		private void menuItem5_Click(object sender, System.EventArgs e)
		{
			Application.Exit();
		}

		private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			listView1.Items.Clear();
			// display the dictionary
			switch(e.Node.Text)
			{
				case "IISProperties":
					dumpDictionary(e.Node.Text);
					break;
			}
		}
		
		private void dumpDictionary(string name)
		{
			try
			{
			
				// due to a damn bug copy the file into a temp direcotry
				fileDest = Environment.GetEnvironmentVariable("TEMP")+@"\file.csc";

				File.Copy(fileName, fileDest, true);
				dict = (Microsoft.CommerceServer.Runtime.IDictionary)fileDoc.ReadFromFile(fileDest, name);
				foreach(string d in dict)
				{
					ListViewItem item = new ListViewItem();
					item.Text = d;
					item.SubItems.Add(dict[d].ToString());
					listView1.Items.Add(item);
				}
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		private void menuItem7_Click(object sender, System.EventArgs e)
		{
			// save changes
			object dummy = dict;
			
			for(int i = 0; i > treeView1.Nodes[0].Nodes.Count; i++)
			{
				fileDoc.WriteToFile(fileName, treeView1.Nodes[0].Nodes[0].Text,ref dummy);
			}
		}

		private void menuItem8_Click(object sender, System.EventArgs e)
		{
			// save as...
			saveFileDialog1.Filter = "Site Server Config files (*.csc)|*.csc|All files (*.*)|*.*";
			if(saveFileDialog1.ShowDialog(this) == DialogResult.OK)
			{
				// save changes
				object dummy = dict;
			
				for(int i = 0; i > treeView1.Nodes[0].Nodes.Count; i++)
				{
					fileDoc.WriteToFile(saveFileDialog1.FileName, treeView1.Nodes[0].Nodes[0].Text,ref dummy);
				}
			}
		}

		private void menuItem9_Click(object sender, System.EventArgs e)
		{
			saveDocument(fileName);
		}

		private void saveDocument(string file)
		{
			// make a DataTable so we can show the value in the next form
			DataTable dt = new DataTable("Table1");
			dt.Columns.Add("Key");
			dt.Columns.Add("Value");

			if(listView1.SelectedItems[0].SubItems[1].Text=="System.__ComObject")
			{
				// get the key pair values
				Microsoft.CommerceServer.Runtime.IDictionary dictionary = (Microsoft.CommerceServer.Runtime.IDictionary)dict[listView1.SelectedItems[0].Text];

				foreach(string d in dictionary)
				{
					DataRow dr = dt.NewRow();
					dr["Key"] = d;
					dr["Value"] = dict[d].ToString();
					dt.Rows.Add(dr);
				}
			}
			else
			{
				DataRow dr = dt.NewRow();
				dr["Key"] = listView1.SelectedItems[0].SubItems[0].Text;
				dr["Value"] = listView1.SelectedItems[0].SubItems[1].Text;
				dt.Rows.Add(dr);
			}

			EditCSC cscEdit = new EditCSC(dt);
			cscEdit.ShowDialog(this);

			// get the table and set the values
			foreach(DataRow dr in cscEdit.dataTbl.Rows)
			{
				// only update if we have a match
				foreach(string d in dict)
				{
					if(d==dr["Key"].ToString())
					{
						dict[d] = dr["Value"].ToString();
					}
				}
			}

			object obj = dict;

			// display the changed dictionary object
			listView1.Items.Clear();
			// display the dictionary
			foreach(string d in dict)
			{
				ListViewItem item = new ListViewItem();
				item.Text = d;
				item.SubItems.Add(dict[d].ToString());
				listView1.Items.Add(item);
			}

			//fileDoc.WriteToFile(file, "IISProperties",ref obj);
		}

		private void DisplayStorageTree(string pwszStorageName, UCOMIStorage storage, TreeNode tn)
		{
			IEnumSTATSTG ppenum;
			UCOMIStorage pStgChild = null;
			STATSTG statstg = new STATSTG();
			int hr = -1;

			try
			{
				// get the elements to enumerate
				hr = storage.EnumElements(0, IntPtr.Zero, 0, out ppenum);

				uint dummy = 0;
				uint i = 1;

				// loop through all elements
				while(0 == ppenum.Next(i, out statstg, out dummy))
				{
					// if type is one then we have a storage
					if(1==statstg.type && @"" !=statstg.pwcsName[0].ToString())
					{
						TreeNode tn2 = new TreeNode(statstg.pwcsName);
						tn.Nodes.Add(tn2);
						hr = storage.OpenStorage(statstg.pwcsName, null, STGM_READ | STGM_SHARE_EXCLUSIVE, null, 0,out pStgChild);

						DisplayStorageTree(statstg.pwcsName, pStgChild, tn2);
					}
					// if type is 2 then we have a stream
					if(2==statstg.type && @"" !=statstg.pwcsName[0].ToString())
					{
						TreeNode tn3 = tn.Nodes.Add(statstg.pwcsName);
						UCOMIStream stream = null;
						storage.OpenStream(statstg.pwcsName, IntPtr.Zero, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, out stream);
						tn3.Tag = "stream";
					}
				}
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		private void loadfile(string file)
		{
			// get the file to work with
			Int64 hr = 0;

			// is the file a compound file?
			hr = ole32.StgIsStorageFile(fileName);

			if(0==hr)
			{
				UCOMIStorage storage = null;
				int grfMode = STGM_READ | STGM_SHARE_DENY_NONE;
				int hResult = ole32.StgOpenStorage(fileName, IntPtr.Zero, grfMode, IntPtr.Zero, 0, out storage);

				//DisplayStorageTree(fileName, storage);
			}
			else
			{
				MessageBox.Show("Not a pup file");
			}
		}

		private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			// try a delete don't worry about errors
			try
			{
				File.Delete(fileDest);
			}
			catch{}
		}


	}
}
